package com.lz.filter.mvcHandlerInterceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

import static com.lz.common.baseBean.StaticString.REDIS_HOW_OFTEN;
import static com.lz.common.baseBean.StaticString.REDIS_KEY_SPLIT;

/**
 * 我想写一个记录所有接口的是应用次数的方法。首先我想到的是注解。然后在写注解的使用范围的时候，
 * 我就觉得如果是每个接口都要执行的话，那就写，支持method级别的还要写type级别的注解，这样更方便。
 * 但是如果每个都要写那还不如写在过滤器或者拦截器中，这样更加的方便，不需要在每个接口处都写注解了，
 * 然后拦截器专注于控制器的请求，过滤器专注于请求参数的处理。
 */
@Component
public class HowOftenInterceptor implements HandlerInterceptor {


    private static final Logger log = LoggerFactory.getLogger(HowOftenInterceptor.class);
    @Autowired
    private StringRedisTemplate redisTemplate;

    //调用时机：在控制器方法（@Controller中的方法）执行之前被调用。
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取
        log.info("记录接口访问次数拦截器");
        // 如果不是控制器方法直接放行
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //获取所在类名和方法名
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        //拼接key
        String key = REDIS_HOW_OFTEN + REDIS_KEY_SPLIT + className + REDIS_KEY_SPLIT + methodName;
        //获取访问次数
        String count = redisTemplate.opsForValue().get(key);
        if (count == null) {
            count = "1";
        } else {
            count = String.valueOf(Integer.parseInt(count) + 1);
        }
        //设置访问次数
        redisTemplate.opsForValue().set(key, count);
        log.info("结束记录接口访问次数拦截器");
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

//    //调用时机：在控制器方法执行之后，但在视图渲染之前被调用。
//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
//    }
//
//    //    调用时机：在视图渲染之后被调用。
//    @Override
//    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
//    }
}
